<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>双视角交易回报计算器 (优化米价版)</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#1e40af',
                        secondary: '#3b82f6',
                        accent: '#60a5fa',
                        neutral: '#f3f4f6',
                        success: '#10b981',
                        warning: '#f59e0b',
                        danger: '#ef4444',
                        info: '#3b82f6',
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .card-shadow {
                box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
            }
            .input-focus {
                @apply focus:ring-2 focus:ring-primary/50 focus:border-primary;
            }
            .btn-hover {
                @apply hover:shadow-lg hover:-translate-y-0.5 transition-all duration-300;
            }
            .advice-card {
                @apply mt-4 p-4 border-l-4 rounded-r-lg;
            }
        }
    </style>
</head>
<body class="bg-gray-50 font-sans text-gray-800 min-h-screen">
    <div class="container mx-auto px-4 py-8 max-w-6xl">
        <header class="text-center mb-10">
            <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-primary mb-2">双视角交易回报计算器</h1>
            <p class="text-gray-600 max-w-2xl mx-auto">从销售方和购买方不同视角，计算并分析交易回报，提供智能谈判建议 (单位: 万)</p>
        </header>

        <div class="grid grid-cols-1 lg:grid-cols-5 gap-8">
            <div class="lg:col-span-2 bg-white rounded-xl p-6 card-shadow transform transition-all duration-300 hover:shadow-xl">
                <h2 class="text-xl font-semibold mb-6 text-primary flex items-center">
                    <i class="fa fa-calculator mr-2"></i>参数输入
                </h2>
                
                <form id="calculator-form" class="space-y-5">
                    <div class="form-group">
                        <label class="block text-sm font-medium text-gray-700 mb-2">测量主体</label>
                        <div class="flex space-x-4" id="subject-selector">
                            <label class="flex items-center p-3 border border-gray-300 rounded-lg cursor-pointer flex-1">
                                <input type="radio" name="subject" value="seller" class="h-4 w-4 text-primary focus:ring-primary" checked>
                                <span class="ml-3 text-sm font-medium text-gray-900">销售方</span>
                            </label>
                            <label class="flex items-center p-3 border border-gray-300 rounded-lg cursor-pointer flex-1">
                                <input type="radio" name="subject" value="buyer" class="h-4 w-4 text-primary focus:ring-primary">
                                <span class="ml-3 text-sm font-medium text-gray-900">购买方</span>
                            </label>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="store-price" class="block text-sm font-medium text-gray-700 mb-1">商店售价 (万)</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-500">万</span>
                            <input type="number" id="store-price" name="store-price" step="any"
                                class="w-full pr-10 pl-3 py-2 border border-gray-300 rounded-lg input-focus outline-none"
                                placeholder="请输入商店售价" required>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="face-to-face-silver" class="block text-sm font-medium text-gray-700 mb-1">面对面交易银两 (万)</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-500">万</span>
                            <input type="number" id="face-to-face-silver" name="face-to-face-silver" step="any"
                                class="w-full pr-10 pl-3 py-2 border border-gray-300 rounded-lg input-focus outline-none"
                                placeholder="请输入交易银两数量" required>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="face-to-face-rmb" class="block text-sm font-medium text-gray-700 mb-1">面对面交易人民币 (元)</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 left-0 pl-3 flex items-center text-gray-500">¥</span>
                            <input type="number" id="face-to-face-rmb" name="face-to-face-rmb" step="any"
                                class="w-full pl-8 pr-3 py-2 border border-gray-300 rounded-lg input-focus outline-none"
                                placeholder="请输入交易人民币金额" required>
                        </div>
                    </div>

                    <div class="grid grid-cols-1 md:grid-cols-2 gap-5">
                        <div class="form-group">
                            <label for="rice-price-min" class="block text-sm font-medium text-gray-700 mb-1">米价最低值 (万)</label>
                             <div class="relative">
                                <span class="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-500">万</span>
                                <input type="number" id="rice-price-min" name="rice-price-min" step="any"
                                    class="w-full pr-10 pl-3 py-2 border border-gray-300 rounded-lg input-focus outline-none"
                                    placeholder="例如: 17" required value="17">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="rice-price-max" class="block text-sm font-medium text-gray-700 mb-1">米价最高值 (万)</label>
                             <div class="relative">
                                <span class="absolute inset-y-0 right-0 pr-3 flex items-center text-gray-500">万</span>
                                <input type="number" id="rice-price-max" name="rice-price-max" step="any"
                                    class="w-full pr-10 pl-3 py-2 border border-gray-300 rounded-lg input-focus outline-none"
                                    placeholder="例如: 20" required value="20">
                            </div>
                        </div>
                    </div>

                    <div class="pt-4">
                        <button type="submit" class="w-full bg-primary text-white font-medium py-3 px-4 rounded-lg btn-hover flex items-center justify-center">
                            <i class="fa fa-calculator mr-2"></i>计算交易回报
                        </button>
                    </div>
                </form>
            </div>

            <div class="lg:col-span-3">
                <div class="bg-white rounded-xl p-6 card-shadow transform transition-all duration-300 hover:shadow-xl">
                    <h2 class="text-xl font-semibold mb-6 text-primary flex items-center">
                        <i class="fa fa-bar-chart mr-2"></i>计算结果
                    </h2>
                    
                    <div id="results-container" class="opacity-0 transition-opacity duration-500">
                        <div id="seller-results" class="space-y-6 hidden"></div>
                        <div id="buyer-results" class="space-y-6 hidden"></div>
                    </div>

                    <div id="initial-prompt" class="text-center py-10 text-gray-500">
                        <i class="fa fa-info-circle text-4xl mb-4 opacity-30"></i>
                        <p>请输入参数并点击计算按钮获取结果</p>
                    </div>
                </div>
                <div id="chart-container" class="bg-white rounded-xl p-6 mt-8 card-shadow opacity-0 transition-opacity duration-500">
                     <h2 class="text-xl font-semibold mb-4 text-primary flex items-center">
                        <i class="fa fa-pie-chart mr-2"></i>指标可视化
                    </h2>
                    <canvas id="transactionChart"></canvas>
                </div>
            </div>
        </div>
    </div>

    <script>
        let transactionChart = null; // 全局图表实例变量

        document.addEventListener('DOMContentLoaded', function() {
            const form = document.getElementById('calculator-form');
            form.addEventListener('submit', function(e) {
                e.preventDefault();
                calculateResults();
            });

            // 确保米价范围合理
            const minInput = document.getElementById('rice-price-min');
            const maxInput = document.getElementById('rice-price-max');
            minInput.addEventListener('change', () => {
                if (parseFloat(minInput.value) > parseFloat(maxInput.value)) maxInput.value = minInput.value;
            });
            maxInput.addEventListener('change', () => {
                if (parseFloat(maxInput.value) < parseFloat(minInput.value)) minInput.value = maxInput.value;
            });
        });

        /**
         * 新增：计算线性递减加权米价
         * @param {number} minPrice - 区间最低价
         * @param {number} maxPrice - 区间最高价
         * @returns {number} - 加权后的米价
         */
        function calculateWeightedRicePrice(minPrice, maxPrice) {
            // 确保输入为整数进行迭代
            const min = Math.round(minPrice);
            const max = Math.round(maxPrice);
            
            if (min > max) return minPrice; // 如果输入不合法，返回最低价
            if (min === max) return minPrice;

            let pricePoints = [];
            for (let i = min; i <= max; i++) {
                pricePoints.push(i);
            }

            const numPoints = pricePoints.length;
            let weightedSum = 0;
            let totalWeights = 0;

            for (let i = 0; i < numPoints; i++) {
                const price = pricePoints[i];
                const weight = numPoints - i; // 权重从高到低递减
                weightedSum += price * weight;
                totalWeights += weight;
            }

            return totalWeights > 0 ? weightedSum / totalWeights : minPrice;
        }

        // 主计算函数
        function calculateResults() {
            const subject = document.querySelector('input[name="subject"]:checked').value;
            const storePrice = parseFloat(document.getElementById('store-price').value);
            const faceToFaceSilver = parseFloat(document.getElementById('face-to-face-silver').value);
            const faceToFaceRmb = parseFloat(document.getElementById('face-to-face-rmb').value);
            const ricePriceMin = parseFloat(document.getElementById('rice-price-min').value);
            const ricePriceMax = parseFloat(document.getElementById('rice-price-max').value);

            if (isNaN(storePrice) || isNaN(faceToFaceSilver) || isNaN(faceToFaceRmb) || isNaN(ricePriceMin) || isNaN(ricePriceMax)) {
                alert('请输入所有有效的数值。');
                return;
            }
            
            const weightedRicePrice = calculateWeightedRicePrice(ricePriceMin, ricePriceMax);

            document.getElementById('initial-prompt').classList.add('hidden');
            document.getElementById('results-container').classList.remove('opacity-0');
            document.getElementById('chart-container').classList.remove('opacity-0');

            if (subject === 'seller') {
                calculateSellerResults(storePrice, faceToFaceSilver, faceToFaceRmb, weightedRicePrice);
            } else {
                calculateBuyerResults(storePrice, faceToFaceSilver, faceToFaceRmb, weightedRicePrice);
            }
        }

        // 计算并显示销售方结果 (已按要求修改)
        function calculateSellerResults(storePrice, faceToFaceSilver, faceToFaceRmb, weightedRicePrice) {
            // 商店交易实际额
            const listingFee = Math.min(storePrice * 0.01, 1); 
            const actualTransactionAmount = storePrice - listingFee - (storePrice * 0.06);
            
            // 核心计算值 (隐式包含3%米价手续费)
            const rmbValueInSilver = faceToFaceRmb * weightedRicePrice * 0.97;

            // 1. 面交购买方出价额 (用于合理率计算)
            const buyerOfferAmount = faceToFaceSilver + rmbValueInSilver;
            
            // 2. 面交实得总值 (扣除13%面交银两手续费后的实际所得)
            const sellerNetReceipts = (faceToFaceSilver * 0.87) + rmbValueInSilver;

            // 面交价格合理率 = 面交购买方出价额 / 商店交易实际额
            const priceReasonablenessRate = buyerOfferAmount / actualTransactionAmount;
            
            // 最低剩余应该收回银两
            const minimumSilverToRecover = storePrice - faceToFaceSilver;
            
            // 弥补亏损率
            const lossCompensationRate = rmbValueInSilver / minimumSilverToRecover;

            let adviceHTML = '';
            // 当面交价格合理率 < 1
            if (priceReasonablenessRate < 1) {
                // 新的公允人民币价格
                const newFairRmbPrice = (actualTransactionAmount - faceToFaceSilver) / (weightedRicePrice * 0.97);
                const fairRmbDifference = newFairRmbPrice - faceToFaceRmb;
                if (fairRmbDifference > 0) {
                    adviceHTML = createAdviceCard('warning', '谈判建议', `当前报价未达到商店净收益。要使价格合理 (合理率=1)，建议将人民币售价提高 <strong class="text-lg">${fairRmbDifference.toFixed(2)}</strong> 元。`);
                }
            // 当面交价格合理率 >= 1 但 弥补亏损率 < 1
            } else if (lossCompensationRate < 1) {
                // 完全弥补人民币额
                const fullCompensationRmb = minimumSilverToRecover / (weightedRicePrice * 0.97);
                const rmbDifference = fullCompensationRmb - faceToFaceRmb;
                if (rmbDifference > 0) {
                    adviceHTML = createAdviceCard('info', '优化建议', `当前报价已盈利，但未完全弥补结构性亏损。要实现完全弥补 (弥补率=1)，建议将人民币售价提高 <strong class="text-lg">${rmbDifference.toFixed(2)}</strong> 元。`);
                }
            }

            const [reasonablenessJudgment, reasonablenessColor] = getJudgment(priceReasonablenessRate, ['赚钱', '价格合理', '亏钱']);
            const [compensationJudgment, compensationColor] = getJudgment(lossCompensationRate, ['完全溢价', '完全弥补', '未完全弥补亏损']);

            const resultsHTML = `
                ${createResultItem('加权米价 (万)', weightedRicePrice.toFixed(2))}
                <hr class="border-gray-200">
                ${createResultItem('商店交易实际额 (万)', actualTransactionAmount.toFixed(2))}
                ${createResultItem('面交购买方出价额 (万)', buyerOfferAmount.toFixed(2))}
                ${createResultItem('面交实得总值 (万)', sellerNetReceipts.toFixed(2))}
                <hr class="border-gray-200">
                ${createResultItemWithJudgment('面交价格合理率', priceReasonablenessRate.toFixed(4), reasonablenessJudgment, reasonablenessColor)}
                ${createResultItemWithJudgment('弥补亏损率', lossCompensationRate.toFixed(4), compensationJudgment, compensationColor)}
                <hr class="border-gray-200">
                ${createResultItem('最低剩余应收回银两 (万)', minimumSilverToRecover.toFixed(2))}
                ${adviceHTML}
            `;
            const sellerResultsDiv = document.getElementById('seller-results');
            sellerResultsDiv.innerHTML = resultsHTML;
            sellerResultsDiv.classList.remove('hidden');
            document.getElementById('buyer-results').classList.add('hidden');

            // 更新图表
            updateChart({
                labels: ['商店净收益', '买方出价额'],
                data: [actualTransactionAmount, buyerOfferAmount],
                title: '销售方收益对比'
            });
        }

        // 计算并显示购买方结果 (此部分未修改)
        function calculateBuyerResults(storePrice, faceToFaceSilver, faceToFaceRmb, weightedRicePrice) {
            const buyerOfferAmount = faceToFaceSilver + faceToFaceRmb * weightedRicePrice;
            const savingsRate = storePrice / buyerOfferAmount;

            let adviceHTML = '';
            if (savingsRate < 1) { // 节省率小于1代表比商店贵
                const fairRmbPrice = (storePrice - faceToFaceSilver) / weightedRicePrice;
                const rmbDifference = faceToFaceRmb - fairRmbPrice;
                if (rmbDifference > 0) {
                     adviceHTML = createAdviceCard('warning', '还价建议', `当前报价比商店还贵。要使价格与商店持平 (节省率=1)，建议将人民币售价减少 <strong class="text-lg">${rmbDifference.toFixed(2)}</strong> 元。`);
                }
            }
            
            const [savingsJudgment, savingsColor] = getJudgment(savingsRate, ['比商店便宜', '等于商店价', '比商店贵']);

            const resultsHTML = `
                ${createResultItem('加权米价 (万)', weightedRicePrice.toFixed(2))}
                <hr class="border-gray-200">
                ${createResultItem('商店售价 (基准成本/万)', storePrice.toFixed(2))}
                ${createResultItem('面交购买方出价额 (万)', buyerOfferAmount.toFixed(2))}
                <hr class="border-gray-200">
                ${createResultItemWithJudgment('面交节省率', savingsRate.toFixed(4), savingsJudgment, savingsColor)}
                ${adviceHTML}
            `;
            const buyerResultsDiv = document.getElementById('buyer-results');
            buyerResultsDiv.innerHTML = resultsHTML;
            buyerResultsDiv.classList.remove('hidden');
            document.getElementById('seller-results').classList.add('hidden');

            // 更新图表
            updateChart({
                labels: ['商店售价', '面交花费'],
                data: [storePrice, buyerOfferAmount],
                title: '购买方成本对比'
            });
        }

        // 更新或创建图表
        function updateChart({ labels, data, title }) {
            const ctx = document.getElementById('transactionChart').getContext('2d');
            
            if (transactionChart) {
                transactionChart.destroy();
            }

            transactionChart = new Chart(ctx, {
                type: 'bar',
                data: {
                    labels: labels,
                    datasets: [{
                        label: '价值 (万)',
                        data: data,
                        backgroundColor: [
                            'rgba(59, 130, 246, 0.6)',
                            'rgba(245, 158, 11, 0.6)'
                        ],
                        borderColor: [
                            'rgba(59, 130, 246, 1)',
                            'rgba(245, 158, 11, 1)'
                        ],
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    plugins: {
                        legend: {
                            display: false
                        },
                        title: {
                            display: true,
                            text: title,
                            font: {
                                size: 16
                            },
                            color: '#374151'
                        }
                    },
                    scales: {
                        y: {
                            beginAtZero: true,
                            ticks: {
                                callback: function(value) {
                                    return value + ' 万';
                                }
                            }
                        }
                    }
                }
            });
        }

        // --- 辅助函数 ---
        function createResultItem(label, value) {
            return `<div class="flex justify-between items-center py-1"><span class="text-gray-600">${label}</span><span class="font-semibold text-lg">${value}</span></div>`;
        }
        function createResultItemWithJudgment(label, value, judgment, colorClass) {
            return `<div class="flex justify-between items-center py-1"><span class="text-gray-600">${label}</span><div class="text-right"><span class="font-semibold text-lg block">${value}</span><span class="text-sm font-medium block mt-1 ${colorClass}">${judgment}</span></div></div>`;
        }
        function createAdviceCard(type, title, text) {
            return `<div class="advice-card bg-${type}/10 border-${type}"><p class="font-semibold text-${type}/80">${title}</p><p class="text-sm text-gray-700 mt-1">${text}</p></div>`;
        }
        function getJudgment(rate, [good, neutral, bad], colors = ['success', 'secondary', 'danger']) {
            if (Math.abs(rate - 1) < 0.0001) return [neutral, `text-${colors[1]}`];
            if (rate > 1) return [good, `text-${colors[0]}`];
            return [bad, `text-${colors[2]}`];
        }
    </script>
</body>
</html>
